import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';

import * as _ from 'lodash';

declare var Keycloak: any;

// 'user' is invalid for PC access, disable it!
const ROLES = ['super', 'admin', 'director', 'doctor', 'header', 'nurse'];

@Injectable()
export class KeycloakService {
  static auth: any = {};
  static user: any;

  static init(): Promise<any> {
    let baseUri = document.baseURI;
    if (!baseUri) {
      const baseTags = document.getElementsByTagName('base');
      baseUri = baseTags.length > 0 ? baseTags[0].href : document.URL;
    }

    let authUri = baseUri;
    const urls = authUri.split(':');
    if (urls.length > 2) {
      authUri = urls[0] + ':' + urls[1];
    }
    if (authUri.endsWith('/')) {
      authUri = authUri.substring(0, authUri.length - 1) + ':8443/auth';
    } else {
      authUri += ':8443/auth';
    }

    const keycloakAuth: any = Keycloak({
      realm: environment.realm,
      url: authUri,
      clientId: environment.resource
    });

    if (!environment.doLoginFlag) {
      KeycloakService.auth.loggedIn = true;
      KeycloakService.auth.authz = keycloakAuth;
      KeycloakService.auth.logoutUrl =
        keycloakAuth.authServerUrl +
        '/realms/SBC-WEBUI-TEST/protocol/openid-connect/logout?redirect_uri=' +
        baseUri;

      this.user = {
        name: 'header',
        role: 'header'
      };

      sessionStorage.setItem('user', JSON.stringify(this.user));
      sessionStorage.setItem('institution', JSON.stringify({
        id: 1,
        ip: 'sbc',
        instName: '护适通'
      }));

      return new Promise((resolve, reject) => {
        resolve();
      });
    }

    KeycloakService.auth.loggedIn = false;

    return new Promise((resolve, reject) => {
      keycloakAuth.init({ onLoad: 'login-required' })
      .success(() => {
        KeycloakService.auth.loggedIn = true;
        KeycloakService.auth.authz = keycloakAuth;
        KeycloakService.auth.logoutUrl =
          keycloakAuth.authServerUrl +
          '/realms/' + keycloakAuth.realm + '/protocol/openid-connect/logout?redirect_uri=' +
          baseUri;

        KeycloakService.auth.authz.loadUserProfile().success(data => {
          this.user = {};
          this.user.name = data.username;

          if (data.attributes && data.attributes['locale']) {
            const locales = data.attributes['locale'];
            if (locales[0]) {
              console.log('Locale was set to ' + locales[0] + ' by Keycloadk.');
              environment.locale = locales[0];
            }
          }

          if (data.attributes && data.attributes['instName']) {
            const instName = data.attributes['instName'][0];
            // save institution info:
            //  - id=0 means id is not identified yet
            //  - id=-1 means no institution info was set!
            sessionStorage.setItem('institution', JSON.stringify({
              instName: instName,
              ip: '',
              id: instName ? 0 : -1
            }));
          } else {
            sessionStorage.setItem('institution', JSON.stringify({
              instName: '',
              ip: '',
              id: -1
            }));
          }

          // this.user.roles = this.assignRole();
          for (let i = 0; i < ROLES.length; i++) {
            if (KeycloakService.auth.authz.hasRealmRole(ROLES[i])) {
              this.user.role = ROLES[i];
              break;
            }
          }

          if (!this.user.role) {
            this.user.role = '';
            console.warn('User ' + this.user.name + ' does not have a qualified role to access the system.');
          } else {
            console.log('User "' + this.user.name + '" logged in with role of "' + this.user.role + '".');
          }

          sessionStorage.setItem('user', JSON.stringify(this.user));

          resolve();
        });
      })
      .error(() => {
        reject();
      });
    });
  }

  hasAnyRole(roles: String[]): boolean {
    for (let i = 0; i < roles.length; i++) {
      if (this.hasRole(roles[i])) {
        return true;
      }
    }

    return false;
  }

  hasRole(role: String): boolean {
    if (environment.doLoginFlag) {
      return KeycloakService.auth.authz.hasRealmRole(role);
    } else {
      return KeycloakService.user.roles === role;
    }
  }

  logout() {
    KeycloakService.auth.loggedIn = false;
    KeycloakService.auth.authz = null;
    window.location.href = KeycloakService.auth.logoutUrl;
  }

  refreshToken(): Promise<string> {
    if (!environment.doLoginFlag) {
      return;
    }

    return new Promise<string>((resolve, reject) => {
      if (KeycloakService.auth.authz.token) {
        KeycloakService.auth.authz
          // refresh token if it will expire in 90 seconds or less
          .updateToken(90)
          .success(() => {
            resolve(<string>KeycloakService.auth.authz.token);
          })
          .error(() => {
            // Force logout!
            this.logout();
            reject('Failed to refresh token');
          });
        } else {
          reject('Not logged in');
        }
    });
  }

  getToken(): string {
    return KeycloakService.auth.authz.token;
  }

  saveUser(user) {
    sessionStorage.setItem('user', JSON.stringify(user));
  }

  getUser() {
    return KeycloakService.user;
  }
}
